package com.dhcc.bpm.common.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @ClassName DateUtils
 * @Description 时间工具类
 * @Author xiafayu
 * @Date 2020/2/21 0021 15:16
 * @Version V1.0
 * @Copyright: 2020 东华软件 . All rights reserved.
 **/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
	public static String YYYY = "yyyy";

	public static String YYYY_MM = "yyyy-MM";

	public static String YYYY_MM_DD = "yyyy-MM-dd";

	public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
	public static String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";

	public static MySimpleDateFormat Y2NO_Mill_FORMAT = new MySimpleDateFormat("yyyyMMddHHmmssSSS");
	public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
	public static final MySimpleDateFormat msdf = new MySimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	SimpleDateFormat sdf = new SimpleDateFormat();
	public static String getSystemDateStringY2NO() {
		Calendar calendar = Calendar.getInstance();
		return Y2NO_Mill_FORMAT.format(calendar.getTime());
	}
	private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
			"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss",
			"yyyy.MM.dd HH:mm", "yyyy.MM", "yyyyMMddHHmmss","yyyyMMdd","HHmmss" };

	/**
	 * 获取当前Date型日期
	 *
	 * @return Date() 当前日期
	 */
	public static Date getNowDate() {
		return new Date();
	}

	/**
	 * 获取当前日期, 默认格式为yyyy-MM-dd
	 *
	 * @return String
	 */
	public static String getDate() {
		return dateTimeNow(YYYY_MM_DD);
	}

	/**
	 * 获取当前日期, 默认格式为yyyyMMddHHmmssSSS
	 *
	 * @return String
	 */
	public static String getDateTimes() {
		return dateTimeNow(YYYYMMDDHHMMSSSSS);
	}

	public static final String getTime() {
		return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
	}

	public static final String dateTimeNow() {
		return dateTimeNow(YYYYMMDDHHMMSS);
	}

	public static final String dateTimeNow(final String format) {
		return parseDateToStr(format, new Date());
	}

	public static final String dateTime(final Date date) {
		return parseDateToStr(YYYY_MM_DD, date);
	}

	public static final String parseDateToStr(final String format, final Date date) {
		return new SimpleDateFormat(format).format(date);
	}

	public static final Date dateTime(final String format, final String ts) {
		try {
			return new SimpleDateFormat(format).parse(ts);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 日期路径 即年/月/日 如2018/08/08
	 */
	public static final String datePath() {
		Date now = new Date();
		return DateFormatUtils.format(now, "yyyy/MM/dd");
	}

	/**
	 * 日期路径 即年/月/日 如20180808
	 */
	public static final String date() {
		Date now = new Date();
		return DateFormatUtils.format(now, "yyyyMMdd");
	}

	/**
	 * 获取年月日时分
	 */
	public static final String dateMinute(Integer past) {
		Calendar c = Calendar.getInstance();
		c.setTime(new Date());
		c.add(Calendar.MINUTE, past);
		Date date = c.getTime();
		return DateFormatUtils.format(date, "yyyyMMddHHmm");
	}

	/**
	 * 获取年月日时分秒
	 */
	public static final String dateSecond(Integer past) {
		Calendar c = Calendar.getInstance();
		c.setTime(new Date());
		c.add(Calendar.SECOND, past);
		Date date = c.getTime();
		return DateFormatUtils.format(date, "yyyyMMddHHmmss");
	}

	/**
	 * 日期路径 即年/月/日 如20180808
	 */
	public static final String dateTime() {
		Date now = new Date();
		return DateFormatUtils.format(now, "yyyyMMddHHmmss");
	}

	/**
	 * 日期路径 即年/月/日 如20180808
	 */
	public static final String getDateTime() {
		Date now = new Date();
		return DateFormatUtils.format(now, "yyyyMMddHHmmss").substring(8,14);
	}


	/**
	 * @Author wangjinghan
	 * @Description  得到数组 ，time=-1就是1小时前
	 * @return:  145511,155511
	 * @date: 2021/1/4 14:56
	 */
	public static final String[] getDateTimeAddOneHour(int time) {
		String[] date=new String[2];
		// Date转换为Calendar
		Calendar calendar = Calendar.getInstance();
//		calendar.setTime(new Date(nowDate));
		/* HOUR_OF_DAY 指示一天中的小时 */
		calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) +time);
//		SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd HHmmss");
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
//		System.out.println("一个小时后的时间：" + df.format(calendar.getTime()));
//		System.out.println("当前的时间：" + df.format(new Date()));
		date[0]=df.format(calendar.getTime());
		date[1]=df.format(new Date());//现在时间
		return date;
	}

	/**
	 * @Author wangjinghan
	 * @Description 获取10min后时间
	 * @date: 2021/1/4 14:58
	 */
	public static String getAfterTenMinute(String date){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		//字符串转Date
		Date date1=dateTime("yyyyMMddHHmmss",date);
		Date afterDate = new Date(date1.getTime() + 600000);
		return sdf.format(afterDate);
	}
	/**
	 * @Author wangjinghan
	 * @Description 获取10s后时间
	 * @date: 2021/1/4 14:58
	 */
	public static String getAddOneHour(String date){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		//字符串转Date
		Date date1=dateTime("yyyyMMddHHmmss",date);
		Date afterDate = new Date(date1.getTime() + 60000);
		return sdf.format(afterDate);
	}
	/**
	 * @Author wangjinghan
	 * @Description 获取10min后时间 =600000, 2小时=7200000
	 * @date: 2021/1/4 14:58
	 */
	public static String getAddTenMinute(String date,int time){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		//字符串转Date
		Date date1=dateTime("yyyyMMddHHmmss",date);
		Date afterDate = new Date(date1.getTime() + time);
		return sdf.format(afterDate);
	}

	/**
	 * @Author wangjinghan
	 * @Description 获取10s后时间
	 * @date: 2021/1/4 14:58
	 */
	public static String getDateMonth(String date){
		SimpleDateFormat sdf = new SimpleDateFormat("MM月dd日");
		//字符串转Date
		Date date1=dateTime("yyyyMMdd",date);
		return sdf.format(date1);
	}
	/**
	 * @Author wangjinghan
	 * @Description yyyy-MM-dd HH:mm
	 * @date: 2021/1/4 14:58
	 */
	public static String getDateFormat(String date){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		//字符串转Date
		Date date1=dateTime("yyyyMMddHHmmss",date);
		return sdf.format(date1);
	}
	/**
	 * @Author wangjinghan
	 * @Description HH:mm:ss
	 * @date: 2021/1/4 14:58
	 */
	public static String getDateHHmmss(String date){
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
		//字符串转Date
		Date date1= dateTime("yyyyMMddHHmmss",date);
		return sdf.format(date1);
	}
	/**
	 * 日期型字符串转化为日期 格式
	 */
	public static Date parseDate(Object str) {
		if (str == null) {
			return null;
		}
		try {
			return parseDate(str.toString(), parsePatterns);
		} catch (ParseException e) {
			return null;
		}
	}

	/**
	 * 获取服务器启动时间
	 */
	public static Date getServerStartDate() {
		long time = ManagementFactory.getRuntimeMXBean().getStartTime();
		return new Date(time);
	}

	/**
	 * 计算两个时间差
	 */
	public static String getDatePoor(Date endDate, Date nowDate) {
		long nd = 1000 * 24 * 60 * 60;
		long nh = 1000 * 60 * 60;
		long nm = 1000 * 60;
		// long ns = 1000;
		// 获得两个时间的毫秒时间差异
		long diff = endDate.getTime() - nowDate.getTime();
		// 计算差多少天
		long day = diff / nd;
		// 计算差多少小时
		long hour = diff % nd / nh;
		// 计算差多少分钟
		long min = diff % nd % nh / nm;
		// 计算差多少秒//输出结果
		// long sec = diff % nd % nh % nm / ns;
		return day + "天" + hour + "小时" + min + "分钟";
	}

	/**
	 * 将日期类型转换为字符串的形式
	 *
	 * @param dateFormat
	 *            转换后的格式
	 * @param date
	 *            需要转换的日期
	 * @return 转换后的字符串
	 * @throws IllegalArgumentException
	 */
	public static String dateToString(String dateFormat, Date date)
			throws IllegalArgumentException {
		if (dateFormat == null || dateFormat.equals("")) {
			throw new IllegalArgumentException("parameter dateFormat is not valid");
		}
		if (date == null) {
			throw new IllegalArgumentException("parameter date is not valid");
		}
		SimpleDateFormat formater = new SimpleDateFormat(dateFormat);
		return formater.format(date);

	}

	/**
	 * 获取指定日期在一个星期中为第几天
	 *
	 * @param date
	 *            yyyyMMdd形式的日期字符串
	 * @return
	 * @throws ParseException
	 *             如果日期字符串开始的字符串无法转化时抛出
	 */
	public static int dayOfWeek(String date) throws ParseException {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(format.parse(date));
		int offset = calendar.get(Calendar.DAY_OF_WEEK);
		if (offset == 1) {
			return 7;
		} else {
			return offset - 1;
		}
	}

	/**
	 * 计算【起始日期】 的【所隔天数】的到期日 【按实际天数计算】
	 *
	 * @param date
	 *            起始日期
	 * @param num
	 *            所隔天数
	 * @return 到期日期
	 * @throws Exception
	 */
	public static String pubDeadLineDay(String date, int num) throws Exception {
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cd = Calendar.getInstance();
		String dqDate;
		try {
			cd.setTime(df.parse(date));
			cd.add(Calendar.DATE, num);
			dqDate = df.format(cd.getTime());
		} catch (ParseException e) {
			throw new Exception("日期转换失败！");
		}
		return dqDate;
	}


	/**
	 * 获取从date开始计算num天以前的日期字符串
	 * @param date
	 * @param num
	 * @return
	 * @throws Exception
	 */
	public static String getLastDay(String date, int num) throws Exception {
		DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		Calendar cd = Calendar.getInstance();
		String dqDate;
		try {
			num = -num;
			cd.setTime(df.parse(date));
			cd.add(Calendar.DATE, num);
			dqDate = df.format(cd.getTime());
		} catch (ParseException e) {
			throw new Exception("日期转换失败！");
		}
		return dqDate.substring(0,8);
	}

	public static String getLastDayByNum(String date, int num) throws Exception {
		DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		Calendar cd = Calendar.getInstance();
		String dqDate;
		try {
			num = -num;
			cd.setTime(df.parse(date));
			cd.add(Calendar.DATE, num);
			dqDate = df.format(cd.getTime());
		} catch (ParseException e) {
			throw new Exception("日期转换失败！");
		}
		return dqDate;
	}
	/**
	 * 获取从date开始计算num天以前的每天的日期字符串
	 * @param date
	 * @param num
	 * @return
	 * @throws Exception
	 */
	public static List<String> getLastDays(String date, int num) throws Exception {
		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		Calendar cd = Calendar.getInstance();
		List<String> dateList = new ArrayList<>();
		try {
			num = -num;
			for(int i = 0;i>num;i--){
				cd.setTime(df.parse(date));
				cd.add(Calendar.DATE, i);
				String dqDate;
				dqDate = df.format(cd.getTime());
				dateList.add(dqDate);
			}
		} catch (ParseException e) {
			throw new Exception("日期转换失败！");
		}
		return dateList;
	}

	/**
	 * 计算某天所在的周的日期范围
	 * @param date
	 * @return
	 * @throws ParseException
	 */
	public static List<String> getWeekEveryDays(String date) throws ParseException {
		DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		Calendar cal = Calendar.getInstance();
		cal.setTime(sdf.parse(date));
		// 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
		int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
		if (1 == dayWeek) {
			cal.add(Calendar.DAY_OF_MONTH, -1);
		}
		// System.out.println("要计算日期为:" + sdf.format(cal.getTime())); // 输出要计算日期
		// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		// 获得当前日期是一个星期的第几天
		int day = cal.get(Calendar.DAY_OF_WEEK);
		// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
		cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
		String imptimeBegin = sdf.format(cal.getTime());
		// System.out.println("所在周星期一的日期：" + imptimeBegin);
		cal.add(Calendar.DATE, 6);
		String imptimeEnd = sdf.format(cal.getTime());
		// System.out.println("所在周星期日的日期：" + imptimeEnd);
		List<String> result = findDates(imptimeBegin,imptimeEnd);
		return result;
	}

	/**
	 * 获取从某天到某天间所有的日期列表
	 * @param dBegin
	 * @param dEnd
	 * @return
	 */
	public static List<String> findDates(String dBegin, String dEnd) throws ParseException {
		DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		List lDate = new ArrayList();
		lDate.add(dBegin.substring(0, 8));
		Calendar calBegin = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calBegin.setTime(df.parse(dBegin));
		Calendar calEnd = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calEnd.setTime(df.parse(dEnd));
		// 测试此日期是否在指定日期之后
		while (df.parse(dEnd).after(calBegin.getTime()))
		{
			// 根据日历的规则，为给定的日历字段添加或减去指定的时间量
			calBegin.add(Calendar.DAY_OF_MONTH, 1);
			lDate.add(df.format(calBegin.getTime()).substring(0, 8));
		}
		return lDate;
	}

	/**
	 *  java 获取 获取某年某月 所有日期（yyyymmdd格式字符串）
	 * @param date
	 * @return
	 */
	public static List<String> getMonthEveryDays(String date){
		Integer year = Integer.valueOf(date.substring(0,4));

		Integer month = Integer.valueOf(date.substring(4,6));
		SimpleDateFormat dateFormatYYYYMMDD = new SimpleDateFormat("yyyyMMdd");
		List<String> fullDayList = new ArrayList<>(32);
		// 获得当前日期对象
		Calendar cal = Calendar.getInstance();
		cal.clear();// 清除信息
		cal.set(Calendar.YEAR, year);
		// 1月从0开始
		cal.set(Calendar.MONTH, month-1 );
		// 当月1号
		cal.set(Calendar.DAY_OF_MONTH,1);
		int count = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		for (int j = 1; j <= count ; j++) {
			fullDayList.add(dateFormatYYYYMMDD.format(cal.getTime()));
			cal.add(Calendar.DAY_OF_MONTH,1);
		}
		return fullDayList;
	}

	public static Date asDate(LocalDate localDate) {
		return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
	}

	public static Date asDate(LocalDateTime localDateTime) {
		return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}

	public static LocalDate asLocalDate(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
	}

	public static LocalDateTime asLocalDateTime(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
	}


	/**
	 * @Author wangjinghan
	 * @Description  加10s
	 * @param: date 10:00:00
	 * @return:
	 * @date: 2021/1/13 13:56
	 */
	public static String plusLocalTime(String date) {
		String[] dates = date.split(":");
		LocalTime localTime  = LocalTime.of(Integer.parseInt(dates[0]), Integer.parseInt(dates[1]), Integer.parseInt(dates[2]), 0);
		LocalTime localTime2 = localTime.plusSeconds(10);//加10s
		//localTime2.toString();
		return localTime2.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
	}


	/**
	 * @Author wangjinghan
	 * @Description  日期加1天
	 * @param:
	 * @return:
	 * @date: 2021/2/22 17:41
	 */
	public static String plusLocalDate(String date) {

		LocalDate localDate  = LocalDate.of(Integer.valueOf(date.substring(0,4)),Integer.valueOf(date.substring(5,6)),Integer.valueOf(date.substring(7,8)));
		LocalDate localDate1 = localDate.plusDays(1);//加1天
		localDate1.toString();
		return localDate1.format(DateTimeFormatter.ofPattern("YYYYMMdd"));
	}

	/**
	 * 获取过去第几天的日期
	 *
	 * @param past
	 * @param pattern
	 * @return
	 */
	public static String getPastDate(int past, String pattern) {
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		Calendar c = Calendar.getInstance();
		c.setTime(new Date());
		c.add(Calendar.DATE, past);
		Date m = c.getTime();
		return format.format(m);
	}

	/**
	 * 获取几个月之前的日期
	 * @param month
	 * @param pattern
	 * @return
	 */
	public static String getLastMonth(int month, String pattern) {
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		Calendar c = Calendar.getInstance();
		//过去一月
		c.setTime(new Date());
		c.add(Calendar.MONTH, month);
		Date m = c.getTime();
		return format.format(m);
	}
	/**
	 * 获取一年前的日期
	 * @return
	 */
	public static String getLastYear(String pattern) {
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		Calendar c = Calendar.getInstance();
		//过去一年
		c.setTime(new Date());
		c.add(Calendar.YEAR, -1);
		Date y = c.getTime();
		return format.format(y);
	}
	/**
	 * 获取一年前的日期
	 * @return
	 */
	public static String getLastYear(int past, String pattern) {
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		Calendar c = Calendar.getInstance();
		//过去一年
		c.setTime(new Date());
		c.add(Calendar.YEAR, past);
		Date y = c.getTime();
		return format.format(y);
	}


	public static String getSystemDateOfString() {
		Calendar calendar = Calendar.getInstance();
		return msdf.format(calendar.getTime());
	}
}
